<?php
/*
 * @Author: CHINAKAIYUAN<sunkaiyuan@namenode.cn>
 * @Date: 2022-02-04 16:53:56
 * @LastEditTime: 2023-10-26 15:21:40
 * @LastEditors: 孙开源 && sunkaiyuan@namenode.cn
 * @Description: 
 */

namespace App\Http\Services\Pro;


use App\Http\Services\Service;

use App\Repositories\ProPlanRepository;
use App\Repositories\MarketOrderRepository;
use App\Repositories\ProPlanStorageRepository;
use App\Repositories\StorageRepository;
use App\Repositories\MpcProYarnRepository;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use App\Models\MpcBacthStorage;
use App\Repositories\MpcMoistureRepository;
use App\Repositories\ProProcessesPassRepository;
use App\Repositories\ProProcessesWipRepository;

/**
 * @property MarketOrderRepository $market
 * @property ProPlanStorageRepository $planstorage
 * @property StorageRepository $storageRepository
 * @property MpcProYarnRepository $mpcyarn
 * @property MpcBacthStorage $batchStorage
 * @property ProProcessesPassRepository $swip
 */
class PlanService extends Service
    {

    public function boot(
        ProPlanRepository $repository,
        MarketOrderRepository $market,
        MpcProYarnRepository $mpcyarn,
        //白纱出库单
        ProPlanStorageRepository $planstorage,
        StorageRepository $storageRepository,
        ProProcessesPassRepository $swip
    ) {
        $this->repository = $repository;
        $this->market     = $market;
        // $this->MpcOtherRepository
        $this->planstorage       = $planstorage;
        $this->storageRepository = $storageRepository;
        $this->mpcyarn           = $mpcyarn;
        $this->swip              = $swip;
        }

    public $batchStorage = null;
    public function list()
        {
        // DB::enableQueryLog();
        $this->repository->relation_models['order'] = ['main'];

        $data = $this->repository->condition(request())->getGrid();
        // dd(DB::getQueryLog());

        return $data;
        }

    public function getOrderByDyelot()
        {
        $request    = request();
        $dyelot     = $request->dyelot;
        $company_id = $request->company_id;
        $color_id   = $request->color_id;
        if (isNotEmpty($dyelot)) {
            $this->repository->whereDyelot($dyelot);
            }
        else {
            $this->repository->whereCompany_id($company_id)->whereColor_id($color_id);
            }
        $order = $this->repository->whereHas("order", function ($query)
            {
            $query->where("delivery_quantity", ">", 0)->whereStatus_id(1);
            })->first()?->order;
        $order?->main->customer->linkman;
        return $order;
        }
    //修改工艺路线
    public function process_route($route_id)
        {
        return $this->repository->whereIn("id", $this->getRequestIds())->get()->filter(function ($plan) use ($route_id)
            {
            $route_details = $plan->process_route->details;
            if ($plan->process_id > 0 && !in_array($plan->process_id, $route_details->pluck("process_id")->toArray())) {

                fail("当前工序状态【{$plan->process->name}】！无法修改加工路线！");
                }
            if ($route_details->last()->process_id == $plan->process_id) {
                fail("当前工序已全部加工完成！无法修改加工路线！");
                }

            if ($plan->process_route_id != $route_id) {
                $plan->process_route_id = $route_id;
                $plan->save();
                }
            });
        }
    public function emergency($emergency_id)
        {
        return $this->repository->whereIn("id", $this->getRequestIds())->get()->filter(function ($plan) use ($emergency_id)
            {
            if ($plan->emergency_id != $emergency_id) {
                $plan->emergency_id        = $emergency_id;
                $plan->order->emergency_id = $emergency_id;

                $plan->save();
                $plan->order->save();
                //有可能未生成排缸单
                if ($plan->pro_pot) {
                    $plan->pro_pot->emergency_id = $emergency_id;
                    $plan->pro_pot->save();
                    }
                }
            });
        }

    public function createYzDyeingPlan($data, $quantity)
        {
        $user     = auth()->user();
        $add_data = [
            'order_code'         => '',
            'plan_id'            => '1',
            'order_id'           => 0,
            'department_id'      => $user->department_id,
            'feeding_ratio'      => 940,
            'material_id'        => $data->material_id,
            'process_route_id'   => 2,
            'lot_name'           => $data->lot_name,
            'color_id'           => $data->color_id,
            'loom_id'            => $data->loom_id,
            'company_id'         => 31,
            'plan_quantity'      => $quantity,
            'pro_quantity'       => $quantity,
            'order_user_id'      => $user->id,
            'outfactory_id'      => 31,
            'classgroup_id'      => $data->classgroup_id,
            'auxiliary_quantity' => $quantity / 25
        ];
        $plan     = $this->repository->autosave($add_data);
        return $this->setStorageData($data['storage_ids'], $plan);
        }
    private function setWipStorageData($wips, $plan)
        {
        $yarn_quantity = $plan->plan_quantity * $plan->feeding_ratio / 1000; //白纱数
        $hank          = 0;
        ProProcessesWipRepository::whereIn("id", $wips)->get()->filter(function ($wip) use ($plan, &$yarn_quantity, &$hank)
            {
            //原染色计划的投料与总绞数
            $wip_yarn_quantity = $wip->feeding_ratio / 1000 * $wip->faultle_quantity;
            $quantity          = 0;

            //如果纱够，根据投纱比和产出计算出白纱重，根据白纱比例计算出要出库的WIP库存
            if ($wip_yarn_quantity >= $yarn_quantity) {
                $quantity      = $yarn_quantity / $wip_yarn_quantity * $wip->faultle_quantity;
                $hank += $yarn_quantity / $wip_yarn_quantity * $wip->hank;
                $yarn_quantity = 0;
                }
            else {
                $quantity      = $wip->faultle_quantity;
                $yarn_quantity = $yarn_quantity - $wip_yarn_quantity;
                $hank += $wip->hank;
                }


            ProPlanStorageRepository::create([
                'pro_plan_id'   => $plan->id,
                'material_id'   => $plan->material_id,
                'dyelot'        => $wip->dyelot,
                'lot_id'        => $plan->lot_id,
                'color_id'      => $plan->color_id,
                'company_id'    => 31,
                'mpc_detail_id' => $wip->id,
                'quantity'      => $quantity,
                'isrepair'      => 1 //复修库存标志
            ]);
            //扣库
            ProProcessesWipRepository::run("subWipStorage", [$wip, $quantity]);
            });
        $plan->hank    = $hank;
        $plan->perhank = $hank / $plan->auxiliary_quantity;
        }

    protected function save()
        {
        $data = request()->toArray();

        $data['pro_quantity'] = $data['plan_quantity'];
        if (is_numeric($data['addqty'] ?? "") && $data['addqty'] > 0) {
            //备货
            $this->createYzDyeingPlan(request(), $data['addqty']);
            }
        unset($data['addqty']);
        $plan = $this->repository->autosave($data);

        $plan->auxiliary_quantity = floor($plan->plan_quantity / $plan->order->quantity * $plan->order->auxiliary_quantity); //打包数
        if ($plan->plan_id != 1) {
            fail("非染色计划，无法新增！");
            }
        if ($plan->order->status_id != 1) {
            fail("订单状态[{$plan->order->status->name}],计划失败！");
            }
        $this->market->setPlanQuantity($plan->order_id, 0 - $plan->plan_quantity);
        if ($plan->isrepair == 0)
            $this->setStorageData($data['storage_ids'], $plan);
        else
            $this->setWipStorageData($data['storage_ids'], $plan);

        $plan->is_export = $plan->order->is_export ?? 0;
        $plan->save();

        return $plan;
        }
    protected function savePlanSwip()
        {
        $data = request()->toArray();
        $pass = $this->swip->swipe($data["wip_id"][0], $data['plan_quantity'], 0, 1, 0, $data['outfactory_id'], null, null, null, $data['location_id']);
        $plan = $pass->target;
        $plan = $plan->toArray();

        $plan['car']   = $data['car'];
        $plan['carry'] = $data['carry'];
        $plan          = $this->repository->autosave($plan);
        //搬运 
        $plan['carry_id'] > 0 && $plan->addCarryItem();
        //运输
        $plan['car_id'] > 0 && $plan->addCarItem("染厂", $plan->outfactory->name);
        return $plan->save();
        }

    private function setStorageData($storage_ids, $plan)
        {
        $yarn_quantity = $plan->plan_quantity * $plan->feeding_ratio / 1000; //白纱数
        $max_quantity  = 0; //最大实发数
        $main_data     = $this->mpcyarn->fieldSave($plan);
        $location_name = [];
        $batchStorage  = null; //做多的批次库存
        $this->storageRepository
            ->whereIn("id", $storage_ids)
            ->orderBy("available_quantity")
            ->get()
            ->map(function ($storage) use (&$yarn_quantity, &$max_quantity, $main_data, &$location_name, $plan, &$batchStorage)
                {
                if ($yarn_quantity > 0) {

                    if ($yarn_quantity >= $storage->available_quantity) {

                        $yarn_quantity           = $yarn_quantity - $storage->available_quantity;
                        $data_quantity           = $storage->available_quantity;
                        $data_auxiliary_quantity = $storage->available_auxiliary_quantity;

                        }
                    else {

                        $data_quantity           = $yarn_quantity;
                        $data_auxiliary_quantity = $yarn_quantity / ($storage->available_quantity / $storage->available_auxiliary_quantity);
                        $yarn_quantity           = 0;

                        }
                    //获取最大发的批次白纱
                    if ($max_quantity < $data_quantity) {
                        $max_quantity = $data_quantity;
                        if (!in_array($storage->location->name, $location_name)) {
                            $location_name[] = $storage->location->name;
                            }
                        $batchStorage = $storage;
                        }
                    $planStorag                     = $this->planstorage->fieldSave($storage);
                    $planStorag->pro_plan_id        = $plan->id;
                    $planStorag->main_id            = $main_data->id;
                    $planStorag->quantity           = $data_quantity;
                    $planStorag->auxiliary_quantity = $data_auxiliary_quantity;
                    $planStorag->save();
                    $planStorag->useStorage("领料出库", $plan->order_code);
                    return $planStorag;
                    }
                });
        if ($yarn_quantity > 0) {
            fail("库存数量不足！");
            }
        //获取检验单
        $moisture = MpcMoistureRepository::whereLot_id($batchStorage['lot_id'])->first();
        if ($moisture == null) {
            fail("白纱检验单不存在！没有净重回潮数据！");
            }
        $yarn_quantity      = $plan->plan_quantity * $plan->feeding_ratio / 1000;
        $available_quantity = $yarn_quantity / $moisture->gross; //领用包数

        $floatqtyb = $available_quantity - floor($available_quantity); //领用包数小数

        $main_data->qtyb = floor($available_quantity); //领用包数整数

        $main_data->hank          = floor($floatqtyb * $moisture->perhank); //领用绞数整数
        $main_data->yarn_quantity = $yarn_quantity;
        $main_data->quantity      = $plan->plan_quantity;
        $main_data->location_name = implode(",", $location_name); //库位
        $main_data->storage_ids   = implode(",", $storage_ids); //库存
        $main_data->pro_plan_id   = $plan->id;
        $main_data->type_id       = $batchStorage['type_id'];
        $main_data->perhank       = floor($available_quantity * $moisture->perhank / $plan->auxiliary_quantity); //打包绞数
        $main_data->save();

        $plan->hank    = $available_quantity * $moisture->perhank;
        $plan->perhank = $main_data->perhank;
        $plan->save();
        return $main_data;
        }
    protected function delete()
        {
        return $this->repository->whereIn("id", $this->getRequestIds())->get()->filter(function ($plan)
            {
            if ($plan->pro_quantity < $plan->plan_quantity) {
                fail("单号：{$plan->order_code}的计划已执行！禁止删除！");
                }
            if ($plan->plan_id == 1) {
                $this->market->setPlanQuantity($plan->order_id, $plan->plan_quantity);
                $yarn = $plan->pro_yarn;
                //有白纱单的删除
                if ($yarn) {
                    if ($yarn->status_id == 1) {
                        fail("删计划失败！白纱出库单已出库！");
                        }
                    $yarn->storage->filter(function ($storage)
                        {
                        $storage->nouseStorage();
                        $storage->delete();
                        });
                    $yarn->delete();
                    }

                $plan->pro_storage->filter(function ($v)
                    {
                    //复修的恢复复修库存
                    if ($v->isrepair == 1) {
                        ProProcessesWipRepository::run("restoreWip", [$v->mpc_detail_id, $v->quantity]);
                        }
                    $v->delete();
                    });
                return $plan->delete();
                }
            else if ($plan->plan_id == 2) {
                return $this->swip->deletePass($plan->pass_id);
                }

            });
        }

    public function printReport()
        {
        $data = [];
        if (request('name') == '外发单') {
            $hanghao = 1;
            $data    = $this->repository->whereIn("id", $this->getRequestIds())->getList()->map(function ($v) use (&$hanghao)
                {
                return [
                    'hanghao'         => $hanghao++,
                    'department_name' => $v->department?->name,
                    'mmc'             => $v->material->spec . $v->material->name,
                    'type_name'       => '色绞',
                    'color_code'      => $v->color->code,
                    'color_name'      => $v->color->name,
                    'qtyb'            => $v->plan_auxiliary_quantity,
                    'qty'             => $v->plan_quantity,
                    'dyelot'          => $v->dyelot,
                    'remark'          => $v->remark,
                    'factory_name'    => $v->outfactory->name,
                    'creator_name'    => $v->creator->name,
                    'createtime'      => $v->created_at,
                ];
                });
            }

        return createReport($data->toArray());
        }
    }